<?php
/**
 * Created by PhpStorm.
 * User: longli
 * VX: isa1589518286
 * Date: 2020/09/07
 * Time: 13:29
 * @link http://www.lmterp.cn
 */

namespace app\admin\controller\pur;

use app\admin\controller\BaseController;
use app\common\library\Tools;
use app\common\model\FinancePayment;
use app\common\model\JobFlowModule;
use app\common\model\Producer;
use app\common\model\ProductStore;
use app\common\model\Purchase;
use app\common\model\SysAttachment;
use app\common\model\Warehouse;
use app\common\service\product\ProductService;
use app\common\service\purchase\PurchaseService;
use app\common\service\system\SystemService;
use think\facade\Validate;

class PurchaseController extends BaseController
{
    protected $moduleName = 'purchase';

    /**
     * 公共赋值
     * @return string
     * @date 2020/12/11
     * @author longli
     */
    protected function loadCommon()
    {
        $this->assign('order_status_wait', [Purchase::ORDER_STATUS_SUG, Purchase::ORDER_STATUS_WAIT]);
        $this->assign("order_cancel", Purchase::ORDER_STATUS_CANCEL);
        $this->assign("check_status", JobFlowModule::$CHECK_STATUS);
        $this->assign("purchase_ing", Purchase::ORDER_STATUS_GENERATE);
        $this->assign("cancel_pay_status", [FinancePayment::PAY_STATUS_NONE, FinancePayment::PAY_STATUS_APPLY]);
        $this->assign("warehouse", Warehouse::getAll());
        $this->assign("order_status", Purchase::$ORDER_STATUS);
        $this->assign("pay_status", FinancePayment::$PAY_STATUS);
        $this->assign("pay_status_none", FinancePayment::PAY_STATUS_NONE);
        $this->assign("pay_status_part", FinancePayment::PAY_STATUS_PART);
    }

    /**
     * 采购列表
     * @return string
     * @date 2020/11/03
     * @author longli
     */
    public function index()
    {
        $this->assign('show_verification', $this->user->hasPermissions('/pur/purchase/verification'));
        if($this->request->isAjax())
        {
            $purchase = Purchase::with(['warehouse', 'info', 'producer'])->order("purchase_id desc");
            // 设置搜索条件
            $this->searchModel($purchase, [
                'eq' => ['order_status', 'pay_status', 'producer_id', 'warehouse_id', 'check_status'],
                'times' => ['delivery_date'],
            ]);
            if($sn = $this->request->post('sn', '', 'trim'))
            {
                $purchase->whereRaw("purchase_sn=? OR producer_sn=?", [$sn, $sn]);
            }
            // 获取分页
            $limit = $this->getPageSize();
            $purchase = $purchase->paginate($limit);
            $this->assign("show_re_btn", [
                Purchase::ORDER_STATUS_RECV, Purchase::ORDER_STATUS_CHE_EX,
                Purchase::ORDER_STATUS_CHE_INFO, Purchase::ORDER_STATUS_IN,
                Purchase::ORDER_STATUS_IN_EX, Purchase::ORDER_STATUS_WAIT_UP,
                Purchase::ORDER_STATUS_IN_PART, Purchase::ORDER_STATUS_IN_SUCC,
            ]);
            $this->assign('in_stock_all', Purchase::ORDER_STATUS_IN_SUCC);
            $this->assign("has_pur_return", $this->user->hasPermissions('/pur/return/add'));
            $this->assign("has_pur_exchange", $this->user->hasPermissions('/pur/exchange/add'));
            $this->assign("list", $purchase->getCollection());
            $this->assign("page", $purchase->render());
            return $this->fetch("lists");
        }
        $this->assign('producer', Producer::getAll());
        return $this->fetch('index');
    }

    /**
     * 录入采购信息
     * @return array|string
     * @date 2020/11/03
     * @author longli
     */
    public function add()
    {
        if($this->request->isPost())
        {
            $json = $this->request->getContent();
            if(!Tools::isJson($json, $data)) $this->error("非法请求");
            $tData = ProductService::getInstance()->parseRequestData($data);
            if($pmsg = $this->validatePur($tData['purchase'])) $this->error($pmsg);
            if($imsg = $this->validatePurInfo($tData['info'])) $this->error($imsg);
            if(($sku = ProductService::getInstance()->batchCheckSku($tData['purchase']['producer_id'], $tData['info']['sku'])) !== true)
                $this->error("SKU【{$sku}】当前供应商无法采购，请检查");
            // 验证是否有审批过
            if(isset($tData['purchase']['purchase_id'])
                && ($purchase = Purchase::get($tData['purchase']['purchase_id']))
                && JobFlowModule::isCheckFinish($purchase)
            ) $this->error("采购单不能被修改");
            // 保存采购单
            $tData['info'] = \app\common\service\product\ProductService::getInstance()->transformToArray($tData['info']);
            PurchaseService::getInstance()->addPurchase($tData)
                ? $this->success("保存成功")
                : $this->error("保存失败");
        }
        else
        {
            $purId = $this->request->get("purchase_id");
            if(!empty($purId))
            {
                $purchase = Purchase::with(['info'])->find(["purchase_id"=>$purId]);
                $this->assign("purchase", $purchase);
                $this->assignCheck($purId);
                $this->assignAttachment($purchase);
            }
            $this->assign("attachment_type_invoice", SysAttachment::FILE_TYPE_INVOICE);
            $this->assign("attachment_type_contract", SysAttachment::FILE_TYPE_CONTRACT);
            $this->assign("", "");
            $this->assign("pay_type", FinancePayment::$PAY_TYPE);
            $this->assign("producer", Producer::getAll());
            $this->assign("is_invoice", Producer::$IS_STATUS);
            $this->assign("warehouse", Warehouse::getAll());
            return $this->fetch('add');
        }
    }

    /**
     * 查看采购单
     * @date 2020/11/07
     * @author longli
     */
    public function info()
    {
        $purId = $this->request->get("purchase_id");
        $purchase = Purchase::get($purId);
        if(empty($purId) || empty($purchase)) $this->error("非法请求");
        $this->assignCheck($purId);
        $this->assign('purchase', $purchase);
        $this->assignAttachment($purchase);
        return $this->fetch('info');
    }

    /**
     * 上传合同发票
     * @date 2020/11/09
     * @author longli
     */
    public function upload()
    {
        $data = $this->request->post();
        if(empty($data['purchase_id'])) $this->error("上传失败，请先录入采购信息");
        // 普通验证
        $validate = Validate::make([
            'path'  => 'require',
            'type'  => 'egt:0',
        ],[
            'path.require' => '文件必传',
            'type.require' => '类型必传',

        ]);
        if(!$validate->batch()->check($data)) $this->error(join(', ', $validate->getError()));
        $rootPath = PurchaseService::getRootPath($data['path']);
        if(!is_file($rootPath)) $this->error("上传失败");
        if(SysAttachment::hasFile($rootPath)) $this->error("请勿重复上传");
        $data += [
            'md5_code' => md5_file($rootPath),
            'id_type' => Purchase::getTable(),
            'ref_id' => $data['purchase_id'],
        ];
        SystemService::getInstance()->addAttachment($data)
            ? $this->success("上传成功")
            : $this->error("上传失败");
    }

    /**
     * 下单, 支持批量下单
     * @date 2020/11/09
     * @author longli
     */
    public function business()
    {
        $ids = $this->request->get("ids");
        if(empty($ids)) $this->error("非法请求");
        $inId = PurchaseService::getInstance()->business($ids);
        !empty($inId)
            ? $this->success("下单成功")
            : $this->error("没有要下单的采购单");
    }

    /**
     * 取消订单
     * @date 2020/12/02
     * @author longli
     */
    public function cancel()
    {
        $ids = $this->request->post("ids");
        $remark = $this->request->post("remark", "", "trim");
        if(empty($ids)) $this->error("非法请求");
        $inId = $noId = [];
        foreach(Purchase::whereIn("purchase_id", $ids)->select() as $item)
        {
            if(!(in_array($item->getData("pay_status"), [FinancePayment::PAY_STATUS_NONE, FinancePayment::PAY_STATUS_APPLY])
                || $item->getData("order_status") <= Purchase::ORDER_STATUS_CANCEL))
            {
                $noId[] = $item->purchase_id;
                continue;
            }
            $inId[] = $item->purchase_id;
            $item->order_status = Purchase::ORDER_STATUS_CANCEL;
            $item->remark .= !empty($remark) ? "【取消订单理由:{$remark}】" : "";
            $item->save();
            // 取消付款单
            FinancePayment::cancelPayment($item->purchase_sn, Purchase::getTable(), $remark);
        }
        $noMsg = "已付款的采购单请走审批流程取消";
        !empty($inId)
            ? $this->success("取消成功" . (!empty($noId) ? "，{$noMsg}" : ""))
            : $this->error($noMsg);
    }

    /**
     * 采购生成付款单
     * @date 2020/12/22
     * @author longli
     */
    public function dopayment()
    {
        $ids = $this->request->get("ids");
        if(!is_array($ids)) $ids = explode(',', $ids);
        $error = [];
        foreach($ids as $id)
        {
            if(($msg = PurchaseService::getInstance()->paymentDate($id)) !== true) $error[] = $msg;
        }
        !empty($error)
            ? $this->error(join("<br>", $error))
            : $this->success("付款单生成成功");
    }

    /**
     * 打印采购单
     * @date 2021/03/12
     * @author longli
     */
    public function print()
    {
        $purId = $this->request->get('ids');
        if(empty($purId)) $this->error('非法操作');
        $purchases = Purchase::whereIn('purchase_id', $purId)->select();
        if($purchases->isEmpty()) $this->error('采购单不存在');
        $pdf = [];
        $pService = \app\common\service\product\ProductService::getInstance();
        $path = config('temp_pdf');
        foreach($purchases as $purchase)
        {
            $filename = "purchase-" . strtotime($purchase->update_time) . ".pdf";
            $absFile = "{$path}{$filename}";
            if(is_file($absFile))
            {
                $pdf[] = $absFile;
            }
            else
            {
                $html = view('print/purchase', [
                    'purchase' => $purchase,
                    'barcode' => $pService->generateBarCode($purchase->purchase_sn, ['is_html' => false]),
                ])->getContent();
                if($temp = $pService->HTML2PDF($html, $path, $filename))
                    $pdf[] = $temp;
            }
        }
        if(empty($pdf)) $this->error('打印失败');
        if(count($pdf) == 1)
        {
            $file = $pdf[0];
        }
        else
        {
            $file = \app\common\service\logistics\ChannelService::getInstance()
                ->mergePdf($pdf, [], $path . Tools::getRandStr('16') . '.pdf');
        }
        $byte = base64_encode(file_get_contents($file));
        $this->success('打印成功', '', ['file' => $byte]);
    }

    /**
     * 删除采购单
     * @date 2020/11/07
     * @author longli
     */
    public function delete()
    {
        $purchaseId = $this->request->get("purchase_id");
        if(empty($purchaseId)) $this->error('非法操作');
        if(($purchase = Purchase::get($purchaseId)) && $purchase->getData('order_status') >= Purchase::ORDER_STATUS_GENERATE)
            $this->error("当前采购单不允许删除");
        PurchaseService::getInstance()->deleteById($purchaseId)
            ? $this->success('删除成功')
            : $this->error('删除失败');
    }

    /**
     * 核销采购单
     * @date 2021/04/09
     * @author longli
     */
    public function verification()
    {
        $purId = $this->request->request('ids');
        if(empty($purId)) $this->error('非法操作');
        $service = PurchaseService::getInstance();
        $ids = explode(',', $purId);
        $succ = $err = [];
        foreach($ids as $pid)
        {
            ($msg = $service->verification($pid)) === true
                ? $succ[] = $pid
                : $err[] = $msg;
        }
        if(!empty($succ) && empty($err))
        {
            $this->success("核销成功");
        }
        else if(!empty($succ) && !empty($err))
        {
            $this->success("部分核销成功");
        }
        $this->error(join('<br/>', $err));
    }

    /**
     * 更新供应商单号
     * @date 2021/04/22
     * @author longli
     */
    public function producer_sn()
    {
        if($this->request->isGet())
        {
            $sn = $this->request->get('producer_sn', '', 'trim');
            $purId = $this->request->get('purchase_id', '', 0);
            if(empty($sn) || empty($purId)) $this->error('非法操作');
            if(!($purchase = Purchase::get($purId))) $this->error('采购单不存在');
            $purchase->producer_sn = $sn;
            $purchase->save();
            $this->success('操作成功');
        }
    }

    /**
     * 验证录入采购信息
     * @param array $data 采购信息
     * @return string
     * @date 2020/11/04
     * @author longli
     */
    private function validatePur($data = [])
    {
        // 普通验证
        $validate = Validate::make([
            'producer_id'  => 'require',
            'pay_type'  => 'require',
            'credit_day'  => 'egt:0',
            'pro_money'  => 'egt:0',
            'logistics_price'  => 'egt:0',
            'delivery_date'  => 'require',
            'contacts'  => 'require',
            'phone'  => 'require',
            'address'  => 'require',

        ],[
            'producer_id.require' => '供应商必须选择',
            'pay_type.require' => '付款方式必选',
            'credit_day.egt' => '账期必须大于等于0',
            'pro_money.egt' => '供应商优惠必须大于等于0',
            'logistics_price.egt' => '物流费用必须大于等于0',
            'delivery_date.require' => '交货日期不能为空',
            'contacts.require' => '联系人不能为空',
            'phone.require' => '联系电话不能为空',
            'address.require' => '收货地址不能为空',
        ]);
        if(!$validate->batch()->check($data)) return join(', ', $validate->getError());
    }

    /**
     * 验证录入采购详情
     * @param array $data 采购详情
     * @return string
     * @date 2020/11/04
     * @author longli
     */
    private function validatePurInfo($data = [])
    {
        Validate::extend("skuExist", function($value)
        {
            $value = trim($value);
            return ProductStore::hasSku($value) ? true : "sku【{$value}】不存在";
        });
        // 普通验证
        $validate = Validate::make([
            'qty'  => 'require|egt:1|integer',
            'price'  => 'require|gt:0',
            'sku'  => 'require|skuExist',

        ],[
            'sku.require' => 'sku必填',
            'qty.require' => '数量必填',
            'qty.egt' => '数量必需大于0',
            'qty.integer' => '数量必需为整数',
            'price.require' => '价格必填',
            'price.gt' => '价格必须大于0',
        ]);
        $t = [];
        foreach($data['price'] as $k => $v)
        {
            $t[] = [
                'sku' => $data['sku'][$k],
                'qty' => $data['qty'][$k],
                'price' => $v,
            ];
        }
        $error = [];
        foreach($t as $v)
        {
            if(!$validate->batch()->check($v)) $error[] = join(', ', $validate->getError());
        }
        return join(',', $error);
    }
}